#include <plc2llvm/Visitor/strategy/var_decls/VisitVar_Decls.h>
#include <plc2llvm/PLCSymbols/Modifiers.h>
#include "plc2llvm/PLCScopeStack.h"
#include "plc2llvm/PLCSymbols/PLCCommonVariable.h"
#include "plc2llvm/utils/Log.h"

VisitVar_Decls *VisitVar_Decls::VisitVar_Decls_Strategy = new VisitVar_Decls();

VisitVar_Decls::VisitVar_Decls() {
    registerMe(plcst::PLCSTParser::RuleVar_Decls);
}

std::any VisitVar_Decls::invoke(antlr4::ParserRuleContext *parserCtx, Visitor *visitor) {
    auto* ctx = dynamic_cast<plcst::PLCSTParser::Var_DeclsContext*>(parserCtx);
    //if constant
    bool ifConst = false;
    if(ctx->CONSTANT()){
        ifConst = true;
    }

    // Access
    // var_decls节点可为prog_decl/method_decl/func_decl/fB_decl/class_decl的子节点，
    // 对于前三者而言这个参数没有意义，在这里默认记录为PRIVATE
    Access accessSpec = PRIVATE;
    if(ctx->access_Spec()){
        std::string accessSpecString = ctx->access_Spec()->getText();
        accessSpec = distinguishAccess(accessSpecString);
    }

    //访问var_Decl_Init
    for(auto* varDeclInitCtx : ctx->var_Decl_Init()){
        //访问一个varDeclInitCtx，获取其中的符号
        std::any varListAnyType = visitor->visit(varDeclInitCtx);
        try{
            //TODO：捕捉bad_any_cast错误
            auto varList = std::any_cast<std::vector<PLCCommonVariable*>>(varListAnyType);
            //获得当前作用域
            auto* currentScope = PLCScopeStack::getTopScope();
            //设置CONSTANT ACCESS参数，并加入符号表
            for(auto* var : varList){
                var->setIfConst(ifConst);
                currentScope->addLocalSymbol(var);
            }
        }
        catch (std::bad_any_cast& e) {
            Error << "VisitVar_Decls::invoke" << e.what();
        }

    }
    return nullptr;
}
